import os
import random
import datetime
import sys
import redis
sys.path.append('/home/blog')
from script.models import UserUser, PaymentPay, UserGame
from faker import Faker
from sqlalchemy import create_engine, select
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
from common import get_rang_date

f = Faker(locale='zh_CN')
tag_list = ['fps','MOBA','卡牌','休闲','模拟','益智','回合','求生',
            '多人','单机','冒险','动作','养成','恋爱','角色扮演',
            '体育','赛车','棋牌','恐怖']
game_names = ['lol','dota2','cf','dnf','拳皇',
              '炉石传说','生化危机','8之路','喋血复仇','剑与远征',
              '梦幻西游','三国杀','传奇','卡丁车','暴力摩托',
              '2408','nba2k15','fifa','欢乐斗地主','中国象棋',
              '中国麻将','绝地8','纸人','港诡实录','九州仙剑传']

category_list = {
    1002:[8,1,16],
    1003:[3,18,12,16],
    1004:[14,8,3,16],
    1026:[10,14,11],
    1025:{4,9,19,16},
    1024:{5,9,18,11},
    1023:{8,13,1,12},
    1022:[18,8,11],
    1021:[5,9,14,16],
    1020:[15,4,12,16],
    1019:[4,6,18,16],
    1018:[13,17,11,1],
    1017:[13,17,18,19],
    1016:[10,17,1,16],
    1015:[5,9,11,16],
    1014:[15,17,13],
    1013:[4,14,9,3],
    1012:[10,13,19,14],
    1011:[10,13,12],
    1010:[4,17,19,16],
    1009:[3,7,14,2],
    1008:[15,10,11],
    1007:[4,9,18,11],
    1006:[15,10,5,9],
    1005:[5,17,11],
}


class Main:
    def __init__(self,config_name):
        if config_name == 'release':
            self.db = 'postgresql://yxg123:123456@106.12.119.119/blog'
        else:
            self.db = 'postgresql://postgres:123456@localhost/blog'
        self.redis = redis.Redis(host='127.0.0.1',port='6379',db=3)
        self.con = self.blog_session()
        for i in range(1002,1027):
            for j in range(1002,1027):
                self.redis.ltrim('%s_common_similarity' % i,1,0)
                self.redis.ltrim('%s_cos_similarity' % i, 1, 0)
                self.redis.ltrim('%s_cos_alpha_similarity' % i, 1, 0)

    def blog_session(self):
        engine = create_engine(self.db, poolclass=NullPool)
        return sessionmaker(bind=engine)()

    def run(self):
        # self.task_user()
        # self.task_payment()
        # self.game_login()
        # self.redis_set()
        self.similarity()

    def result(self,first,second):
        set1 = set(first)
        set2 = set(second)
        iset = set1.intersection(set2)
        return len(list(iset))/len(first)*0.5

    def similarity(self):
        for i in range(1002,1027):
            for j in range(1002,1027):
                if i == j:
                    self.redis.rpush('%s_common_similarity' % i, 1)
                    self.redis.rpush('%s_cos_similarity' % i, 1)
                    self.redis.rpush('%s_cos_alpha_similarity' % i, 1)
                else:
                    reg_nums = int(self.redis.hget('%s_total'%i,'reg_nums'))
                    other_reg_nums = int(self.redis.hget('%s_total'%j,'reg_nums'))
                    sql = '''select count(*) same from 
                             (select distinct(user_id) from user_game where game_id=%s ) a ,
                             (select distinct(user_id) from user_game where game_id=%s ) b where
                             a.user_id=b.user_id'''%(i,j)
                    obj = self.con.execute(sql).fetchone()
                    common_r = round(obj.same/reg_nums,2)
                    cos_r = round(obj.same/pow(reg_nums*other_reg_nums,0.5),2)
                    widget = self.result(category_list.get(i),category_list.get(j))
                    cos_alpha_r = round(obj.same/(reg_nums**(1-widget) * other_reg_nums**widget),2)
                    self.redis.rpush('%s_common_similarity' % i, common_r)
                    self.redis.rpush('%s_cos_similarity' % i, cos_r)
                    self.redis.rpush('%s_cos_alpha_similarity' % i, cos_alpha_r)

    def redis_set(self):
        week_start, week_end = get_rang_date(1)
        month_start, month_end = get_rang_date(2)
        year_start, year_end = get_rang_date(3)
        login_sql = ''' select game_id,count(*) login_nums,count(distinct(user_id)) reg_nums 
                        from user_game where insert_time between '%s' and '%s'
                        group by game_id order by game_id'''
        pay_sql = ''' select sum(user_pay_money) total ,game_id,count(distinct(user_id)) pay_nums 
                      from payment_pay where order_date between '%s' and '%s'
                      group by game_id order by game_id'''
        total_login_objs = self.con.execute(login_sql %(datetime.date(2021,1,1),datetime.date(2022,12,31))).fetchall()
        total_pay_objs = self.con.execute(pay_sql %(datetime.date(2021,1,1),datetime.date(2022,12,31))).fetchall()
        week_login_objs = self.con.execute(login_sql % (week_start, week_end+datetime.timedelta(1))).fetchall()
        week_pay_objs = self.con.execute(pay_sql % (week_start, week_end)).fetchall()
        month_login_objs = self.con.execute(login_sql % (month_start, month_end+datetime.timedelta(1))).fetchall()
        month_pay_objs = self.con.execute(pay_sql % (month_start,month_end)).fetchall()
        year_login_objs = self.con.execute(login_sql % (year_start, year_end+datetime.timedelta(1))).fetchall()
        year_pay_objs = self.con.execute(pay_sql % (year_start, year_end)).fetchall()
        for i,obj in enumerate(total_login_objs):
            self.redis.hset('%s_total' %obj.game_id, mapping={'reg_nums':obj.reg_nums,'login_nums':obj.login_nums,
                                                              'pay_nums':total_pay_objs[i].pay_nums,
                                                              'total':total_pay_objs[i].total})
            self.redis.hset('%s_year' %obj.game_id, mapping={'reg_nums': year_login_objs[i].reg_nums,
                                                             'login_nums': year_login_objs[i].login_nums,
                                                             'pay_nums': year_pay_objs[i].pay_nums,
                                                             'total': year_pay_objs[i].total})
            self.redis.hset('%s_month' %obj.game_id, mapping={'reg_nums': month_login_objs[i].reg_nums,
                                                              'login_nums': month_login_objs[i].login_nums,
                                                              'pay_nums': month_pay_objs[i].pay_nums,
                                                              'total': month_pay_objs[i].total})
            self.redis.hset('%s_week' %obj.game_id, mapping={'reg_nums': week_login_objs[i].reg_nums,
                                                             'login_nums': week_login_objs[i].login_nums,
                                                             'pay_nums': week_pay_objs[i].pay_nums,
                                                             'total': week_pay_objs[i].total})
    def task_payment(self):
        l = random.randint(200, 400)
        users = self.con.execute(select(UserUser.id)).fetchall()
        user_ids = [user[0] for user in users]
        for i in range(l):
            user_id = random.choice(user_ids)
            game_id = random.randint(1002, 1026)
            pay_type = random.randint(1, 3)
            order_date = f.date_between_dates(datetime.date(2021, 1, 1), datetime.date.today())
            order_time = order_date.strftime('%Y-%m-%d ') + f.time()
            order_time = datetime.datetime.strptime(order_time, '%Y-%m-%d %H:%M:%S')
            user_pay_money = random.randint(1, 100)
            order_status = random.choice([0,1])
            payment = PaymentPay(user_id=user_id, game_id=game_id, pay_type=pay_type, user_pay_money=user_pay_money,
                                 order_date=order_date, order_time=order_time,order_status=order_status)
            self.con.add(payment)
        self.con.commit()

    def game_login(self):
        start_time = datetime.datetime.strptime('2021-01-01 00:00:00','%Y-%m-%d %H:%M:%S')
        end_time = datetime.datetime.strptime('2022-6-30 23:59:59','%Y-%m-%d %H:%M:%S')
        sql = '''select id from user_user order by random() limit 3000'''
        user_ids = list(set([i.id for i in self.con.execute(sql).fetchall()]))
        for user_id in user_ids:
            insert_time = f.date_time_between(start_time,end_time)
            obj = UserGame(user_id=user_id,game_id=random.choice(range(1002,1027)),insert_time=insert_time)
            self.con.add(obj)
        self.con.commit()

    def task_user(self):
        names = []
        for i in range(random.randint(100,300)):
            name = f.name()
            tag = list(set(random.choices(population=tag_list, k=3)))
            while name in names:
                name = f.name()
            reg_date = datetime.datetime.today()
            reg_time = datetime.datetime.today().strftime('%Y-%m-%d ') + f.time()
            obj = UserUser(name=name, like_game_tag=tag, reg_time=reg_time,reg_date=reg_date)
            self.con.add(obj)
            names.append(f.name())
        for i in range(1000):
            name = f.name()
            tag = list(set(random.choices(population=tag_list, k=3)))
            while name in names:
                name = f.name()
            reg_date = f.date_between_dates(datetime.date(2021, 1, 1),datetime.date(2022, 6, 30))
            reg_time = reg_date.strftime('%Y-%m-%d ') + f.time()
            obj = UserUser(name=name, like_game_tag=tag, reg_time=reg_time,reg_date=reg_date)
            self.con.add(obj)
            names.append(f.name())
        self.con.commit()


if __name__ == '__main__':
    if len(sys.argv)==2:
        config_name = sys.argv[1]
    else:
        config_name = 'local'
    main = Main(config_name)
    main.run()
